package org.dfl.core.model.analysis;

import java.util.Iterator;

import org.dfl.core.model.Place;

public class RPlace extends RSimplePlace {

	public RPlace() {};
	
	public RPlace(Place p) {
		this.setId(p.getId());
	}

	public void reconnectOutputEdges(RPlace p) {
		this.disconnectAllOutputEdges();
		for (REdge e: p.getOutputEdges()) {
			RTransition t = e.getTransition();
			e.connectPlaceToTransition(this, t);
		}
		p.removeOutputEdges();
	}
	
	public void disconnectAllInputEdges() {
		for (REdge e: this.getInputEdges()) {
			e.getTransition().removeOutputEdge(e);
		}
		this.removeInputEdges();
	}
	
	public void disconnectAllOutputEdges() {
		for (REdge e: this.getOutputEdges()) {
			e.getTransition().removeInputEdge(e);
		}
		this.removeOutputEdges();
	}

	public boolean equalsInput(RPlace p) {
		if (p.getInputEdges().size() == this.getInputEdges().size()) {
			int matched = 0;
			for (REdge e1: this.getInputEdges()) {
				boolean found = false;
				Iterator<REdge> ei = p.getInputEdges().iterator();
				while ((!found) && (ei.hasNext())) {
					REdge e2 = ei.next();
					if (e1.getTransition().equals(e2.getTransition())) {
						found = true;
						if (e1.getFlag() == e2.getFlag()) {
							matched++;
						}
					}
				}
			}
			if (matched == this.getInputEdges().size()) {
				return true;
			}
		}
		return false;
	
	}
	
	public boolean equalsOutputExcept(RPlace p) {
		if (p.getOutputEdges().size() == this.getOutputEdges().size()) {
			int matched = 0;
			for (REdge e1: this.getOutputEdges()) {
				boolean found = false;
				Iterator<REdge> ei = p.getOutputEdges().iterator();
				while ((!found) && (ei.hasNext())) {
					REdge e2 = ei.next();
					if (e1.getTransition().equals(e2.getTransition())) {
						found = true;
						if (((!e1.isAnnotated()) && (!e2.isAnnotated()) && (e1.isNested() == e2.isNested())) ||
							((e1.isAnnotated()) && (!e2.isAnnotated()))) {
							matched++;
						}
					}
				}
			}
			if (matched == this.getOutputEdges().size()) {
				return true;
			}
		}
		return false;
	}
	
	public REdge findMatchingOutputEdge(REdge e1) {
		for (REdge e2: this.getOutputEdges()) {
			if ((!e1.equals(e2)) && (e2.getFlag() == -e1.getFlag())) {
				RTransition t1 = e1.getTransition();
				RTransition t2 = e2.getTransition();
				if ((t1.equalsInputExcept(t2, this)) && (t1.equalsOutput(t2))) {
					return e2;
				}
			}
		}
		return null;
	}

	public RPlace findMatchingPlace() {
		boolean found = false;
		Iterator<REdge> iter1 = this.getOutputEdges().iterator();
		while ((!found) && (iter1.hasNext())) {
			REdge e1 = iter1.next();
			if (e1.getTransition().getInputEdges().size() > 1) {
				RTransition t1 = e1.getTransition();
				Iterator<REdge> iter2 = t1.getInputEdges().iterator();
				while ((!found) && (iter2.hasNext())) {
					REdge e2 = iter2.next();
					RPlace p2 = e2.getPlace();
					if ((!equals(p2)) && (equalsInput(p2)) && (equalsOutputExcept(p2))) {
						return p2;
					}
				}
			}
		}
		return null;
	}
}